package com.research.performace.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author SUCCESS\tungo
 *
 * @param <T>
 * @param <Serializable>
 */
public class DAO<T, ID extends Serializable> {

	@Autowired
	private SessionFactory sessionFactory;

	private Class<T> model;

	public DAO() {	}

	public DAO(Class<T> model) {
		this.model = model;
	}
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	protected Criteria getCriteria() {
		return getSession().createCriteria(model);
	}

	@SuppressWarnings("unchecked")
	public T save(T t) {
		return load((ID)getSession().save(t));
	}

	@SuppressWarnings("unchecked")
	public T save(T t, boolean isFlush) {
		t = load((ID)getSession().save(t));
		if (isFlush) {
			getSession().flush();
			getSession().refresh(t);
		}
		return t;
	}

	public void update(T t) {
		getSession().update(t);
	}

	public void saveOrUpdate(T t) {
		getSession().saveOrUpdate(t);
	}

	@SuppressWarnings("unchecked")
	public T merge(T t) {
		return (T)getSession().merge(t);
	}

	public void delete(T t) {
		getSession().delete(t);
	}

	@Transactional
	public void save(List<T> list) {
		for (T t : list) {
			save(t);
		}
	}

	@SuppressWarnings("unchecked")
	public T get(ID id) {
		return (T) getSession().get(model, id);
	}

	@SuppressWarnings("unchecked")
	public T get(ID id, boolean lock) {
		return (T) getSession().get(model, id, LockOptions.UPGRADE);
	}

	@SuppressWarnings("unchecked")
	public T load(ID id) {
		return (T) getSession().load(model, id);
	}

	@SuppressWarnings("unchecked")
	public T load(ID id, boolean lock) {
		return (T) getSession().load(model, id, LockOptions.UPGRADE);
	}

	@Transactional
	public List<T> findAll() {
		return findByCriteria();
	}

	@SuppressWarnings("unchecked")
	protected List<T> findByCriteria(Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(model);

		for (Criterion criterion : criterions) {
			criteria.add(criterion);
		}

		return criteria.list();
	}

}
